import * as events from 'events';

export type FlushOptions = {
  flushInterval?: number,
  maxItems?: number
}
export class BufferFlusher extends events.EventEmitter {

  private buffer = [];
  private flushInterval: number;
  private maxItems: number;
  private flushTimeoutId: ReturnType<typeof setTimeout>;

  constructor(options: FlushOptions = {}) {
    super();
    this.flushInterval = options.flushInterval || 10000;
    this.maxItems = options.maxItems || 5;
    this.flush();
  }

  get() { return this.buffer; }
  clear() { this.buffer = []; }
  stop() { clearTimeout(this.flushTimeoutId); }

  add(data: string) {
    if (data) {
      this.buffer.push(data);
      if (this.buffer.length >= this.maxItems) {
        this.flush();
      }
    }
  }

  flush() {
    this.stop();
    // The timer is the only action that would hold the node-process open. 
    // By unref-ing it, the process will exit prior to the timeout callback execution
    this.flushTimeoutId = setTimeout(() => this.flush(), this.flushInterval).unref();

    if (!this.buffer.length) { return; }

    try {
      this.emit('flush', this.buffer);
    } catch (err) {
      // 当事件被触发时，如果没有与该事件绑定的函数的话，该事件会被静默忽略掉
      // 但是如果事件的名称是 error 的话，没有与此相关的事件处理的话，程序就会 crash 退出
      this.emit('error', err);
    }

    this.buffer = [];
  }
}

// const buffer = new FlushBuffer({ flushInterval: 2000, maxItems: 1 });

// buffer.on('flush', (data) => {
//   console.log(data); // bla
//   console.log(data[0]); // bla
//   // throw new Error('222');
// });

// buffer.add('woaini');

// setTimeout(() => {
//   console.log('程序结束了...');
// }, 20000);